Skip to content

[FS] Prevent duplicate Field Service customer assets during item synchronization - #11094

Open
tomasevicst wants to merge 29 commits into
mainfrom
bugs/649195_FS_Duplicate_Field_Service_Customer_Asset_Created
Open

tomasevicst wants to merge 29 commits into
mainfrom
bugs/649195_FS_Duplicate_Field_Service_Customer_Asset_Created

Conversation

@tomasevicst

@tomasevicst tomasevicst commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

What & why

Business Central and Field Service could both create a Customer Asset for the same item, resulting in duplicates when a Work Order was completed.

This change keeps Business Central as the source for Customer Asset creation by:

  • Setting Convert to Customer Asset to No for Products synchronized from BC Items.
  • Adding the rule to the default Item-Product mapping.
  • Removing the Product flag as a filter for Service Item synchronization.
  • Adding tests for runtime enforcement and mapping configuration.

Linked work

Fixes AB#649195

How I validated this

  • I read the full diff and it contains only changes I intended.
  • I built the affected app(s) locally with no new analyzer warnings.
  • I ran the change in Business Central and confirmed it behaves as expected.
  • I added or updated tests for the new behavior, or explained below why none are needed.

What I tested and the outcome (required — be specific: scenarios, commands, screenshots for UI changes)

Risk & compatibility

Risk is low and limited to coupled Field Service Products. Their Convert to Customer Asset value is overwritten to No during Item synchronization, preventing native Field Service asset creation.

Uncoupled Field Service Products are unaffected. No schema or public API changes are introduced. Existing configurations are covered by runtime enforcement, while reset or newly created mappings receive the constant outbound mapping.

@tomasevicst
tomasevicst requested a review from a team September 5, 2026 09:44
@tomasevicst
tomasevicst requested a review from a team as a code owner September 5, 2026 09:45
@github-actions github-actions Bot added AL: Apps (W1) Add-on apps for W1 Ownership: Needs Review Ownership is Other, low confidence, or needs manual correction Team: Other GitHub request for other area than SCM, Finance or Integration labels Sep 5, 2026
@github-actions github-actions Bot added this to the Version 30.0 milestone Sep 5, 2026
@tomasevicst tomasevicst added the Team: SCM GitHub request for SCM area label Sep 5, 2026
@github-actions github-actions Bot removed the Team: SCM GitHub request for SCM area label Sep 5, 2026
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟡\ Medium\ Severity\ —\ Testing}$

The removed IgnoreServiceItem* tests, and the new ItemSynchronizationDisablesCustomerAssetConversion test, both call the helper procedure directly rather than exercising the actual dispatch path. Critically, the new 'Item-CRM Product' case added to OnBeforeTransferFieldData (which does DestinationRecordRef.SetTable(CRMProduct) / DisableCustomerAssetConversion(...) / DestinationRecordRef.GetTable(CRMProduct)) is never exercised by any test — no test drives an Item-to-CRMProduct transfer through the RecordRef dispatch to confirm the case is reached and the record is written back correctly. Add an integration-style test that triggers the Item-CRM Product transfer path (e.g. via the subscriber's OnBeforeTransferFieldData or a full sync call) and asserts the resulting CRM Product has ConvertToCustomerAsset = false.

Line mapping was unavailable, so this was posted as an issue comment.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.38.6

Comment thread src/Apps/W1/FieldServiceIntegration/test/src/FSIntegrationTest.Codeunit.al Outdated
…procedure to streamline service item synchronization
…re and update test cases for service item synchronization
Comment thread src/Apps/W1/FieldServiceIntegration/test/src/FSIntegrationTest.Codeunit.al Outdated
Comment thread src/Apps/W1/FieldServiceIntegration/test/src/FSIntegrationTest.Codeunit.al Outdated
Comment thread src/Apps/W1/FieldServiceIntegration/test/src/FSIntegrationTest.Codeunit.al Outdated
CRMProduct.ConvertToCustomerAsset := false;
CRMProduct.Insert(false);
// [GIVEN] A coupled item and product where Convert to Customer Asset is Yes.
CRMSetupDefaults.ResetItemProductMapping('ITEM-PRODUCT', false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Testing}$

The new Item-to-CRM Product sync test (ItemSynchronizationDisablesCustomerAssetConversion) only exercises an already-coupled, pre-existing product via CreateCoupledItemAndProduct, so it never covers the new DestinationIsInserted = true branch added in OnAfterTransferRecordFields (the conditional LoadFields(ConvertToCustomerAsset) path taken when a CRM Product is newly created from an item). Add a test case that synchronizes an uncoupled item so a new CRM Product is inserted, and assert the resulting ConvertToCustomerAsset is correctly initialized/disabled.

Agent judgement — not directly backed by a BCQuality knowledge article.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.41.6

IntegrationFieldMapping.Direction::ToIntegrationTable,
'', false, false);

// Business Central service items are the source for Field Service customer assets.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Upgrade}$

The new 'Item-CRM Product' synchronization branch and its Item-Product field mapping constant (ConvertToCustomerAsset = 'false') change the intended behavior for existing tenants: previously-coupled items and their CRM Products keep their pre-30.0 field mapping and Convert-to-Customer-Asset state until a user manually runs 'Reset Configuration' or a full resync occurs. No upgrade code migrates already-installed Integration Field Mapping rows or already-coupled CRM Product records to the new 'service items always synchronize' design, so the fix does not apply safely to tenants that upgrade without manual intervention.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.41.6

end;

/// <summary>
/// Retained for compatibility. Service items are now always synchronized to Field Service customer assets, so this procedure leaves the synchronization decision unchanged.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Breaking\ Changes}$

The obsolete public test-library procedure IgnoreServiceItemsByConvertToCustomerAssetFlag (Microsoft.TestLibraries.DynamicsFieldService, FSIntegrationTestLibrary.Codeunit.al) is correctly marked [Obsolete('...', '30.0')], but its body was replaced with an empty no-op instead of continuing to forward to the previous implementation. During the deprecation window, existing external callers who still invoke this public procedure expecting IgnoreRecord to be set now silently receive unchanged behavior. Guidance on deprecating public members with the Obsolete lifecycle recommends preserving the prior behavior (e.g., keep forwarding to the codeunit's still-present implementation, or otherwise retain the previous decision) until the procedure is actually removed in a later release, rather than emptying it immediately upon obsoletion.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.41.6

'Item-CRM Product':
begin
DestinationRecordRef.SetTable(CRMProduct);
if DestinationIsInserted then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Testing}$

The new 'Item-CRM Product' case branch in OnAfterTransferRecordFields has a DestinationIsInserted path that calls CRMProduct.LoadFields(ConvertToCustomerAsset) before disabling customer-asset conversion, but the new tests (ItemSynchronizationDisablesCustomerAssetConversion, ItemProductMappingDisablesCustomerAssetConversion) only exercise the already-coupled/update path via CreateCoupledItemAndProduct. No test drives CRMIntegrationTableSynch.SynchRecord through a path where the CRM Product record is newly inserted, so the DestinationIsInserted = true branch (and its LoadFields call) is not covered by this change.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.41.6

@JesperSchulz Jesper Schulz-Wedde (JesperSchulz) added Team: SCM GitHub request for SCM area and removed Team: Other GitHub request for other area than SCM, Finance or Integration Ownership: Needs Review Ownership is Other, low confidence, or needs manual correction labels Sep 21, 2026
@github-actions github-actions Bot added Ownership: Needs Review Ownership is Other, low confidence, or needs manual correction Team: Other GitHub request for other area than SCM, Finance or Integration and removed Team: SCM GitHub request for SCM area labels Sep 21, 2026
@github-actions github-actions Bot added Team: SCM GitHub request for SCM area and removed Team: Other GitHub request for other area than SCM, Finance or Integration Ownership: Needs Review Ownership is Other, low confidence, or needs manual correction labels Sep 21, 2026
@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 1

Recommendation: Accept with Suggestions

What this PR does

This change keeps Business Central as the source for Field Service customer assets for synchronized items. It removes the service-item filter that depended on the Product's Convert to Customer Asset flag, and it adds item-product synchronization logic that turns that flag off for coupled items.

The main behavior looks correct for the reported duplicate-asset scenario. The service-item mapping depends on the item-product mapping, the new item-product transfer path uses the coupling state to derive the Product value, and the tests cover both the mapping setup and a coupled item/product synchronization. The relevant integration event publishers and call sites were checked, including the field-modified and transfer-field hooks used by this change.

Problem-solution fit

Fit: Strong

The reported problem is that both systems can create a customer asset for the same equipment. The change addresses the root cause by always allowing the Business Central service item to synchronize and by disabling native Field Service customer asset conversion on coupled Products.

Suggestions

S1 (🟠 Moderate): Guard field-modified handling when disabled
Add the same FSConnectionSetup.IsEnabled() guard here that OnTransferFieldData uses. If the mapping is still present after Field Service is disabled, this handler can mark the field as modified while the transfer handler exits, so synchronization can fall back to copying the wrong value.

Risk assessment and necessity

Risk: The main regression surface is item-to-Product synchronization and service-item-to-customer-asset synchronization for coupled Field Service data. The change is not financial posting logic and does not change schema, but it changes integration behavior for coupled Products and can affect customers that rely on native Field Service conversion for those Products.

Necessity: The change is needed because the old Product flag could suppress Business Central customer-asset synchronization while still allowing Field Service to create another asset during work order completion. The scope is targeted: it keeps service items synchronizing and moves the conflict prevention to the item-product mapping where the Product flag is maintained.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=1 by=alexei-dobriansky at=2026-09-21T12:13:08.5984330Z lastSha=c5796a5023449a01544ea4228b5cc8de435d4502 reviewKey=0d24fd740440a636e26d7079fcacd6e978a82a52468ad3a95333da6d590029a7 suggestions=S1@57bf2917

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 2

Recommendation: Accept

What this PR does

The latest change addresses the remaining field-comparison gap from round 1. The field-modified subscriber now uses the same Field Service enabled guard as the transfer subscriber, and the added test verifies that the comparison hook stays unhandled when integration is disabled.

The current diff still fits the reported duplicate-customer-asset scenario. The item-product mapping derives Convert to Customer Asset from the item coupling state, service items are no longer skipped by that Product flag, and the comparison and transfer hooks now stay consistent when Field Service integration is off.

Status of previous suggestions
ID Title Status Author response
S1 Guard field-modified handling when disabled Addressed N/A
New observations (commits since round 1)

None - changes only addressed the previous suggestion.

Risk assessment and necessity

Risk: The regression surface remains item-to-Product synchronization and service-item-to-customer-asset synchronization for coupled Field Service data. The latest change lowers the disabled-integration risk by making field comparison and field transfer follow the same guard.

Necessity: The change is still needed to prevent both systems from creating customer assets for the same equipment. The round-2 change is also necessary because it keeps the new mapping inactive when Field Service integration is disabled.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=2 by=alexei-dobriansky at=2026-09-22T00:41:21.760Z lastSha=e8302a63d9db4358400aaac00b19e1801fc4ef13 reviewKey=50f4f3d160acbc5279ec1710a9ba3d94a60de2955143cdd254f18927dca0c431 suggestions=S1@57bf2917:addressed parentRound=1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: Apps (W1) Add-on apps for W1 Team: SCM GitHub request for SCM area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants